package com.yesep.learn.mqtt.client.session;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.yesep.learn.mqtt.client.common.TimeOutMap;

import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader;
import io.netty.handler.codec.mqtt.MqttPublishMessage;
import io.netty.handler.codec.mqtt.MqttPublishVariableHeader;

/**
 * 
 * @Description:
 */
public class MemorySession<K, V> implements Session<K, V> {

	private TimeOutMap<Integer, MqttMessage> waitingForConfirmMap = new TimeOutMap<>(60);
	private ConcurrentMap<Integer, MqttPublishMessage> retainedMap = new ConcurrentHashMap<>();
	private ConcurrentMap<K, V> attrMap = new ConcurrentHashMap<>();

	@Override
	public void retainMessage(MqttPublishMessage msg) {
		retainedMap.put(msg.variableHeader().messageId(), msg);
	}

	@Override
	public MqttPublishMessage removeRetain(int id) {
		return retainedMap.remove(id);
	}

	@Override
	public List<MqttPublishMessage> retainedMessage() {
		return new ArrayList<>(retainedMap.values());
	}

	@Override
	public void waitingConfirm(MqttMessage msg) {
		waitingForConfirmMap.put(getId(msg), msg);
	}

	@Override
	public MqttMessage confirmMessage(int id) {
		return waitingForConfirmMap.remove(id);
	}

	@Override
	public List<MqttMessage> waitingConfirmMessage() {
		return new ArrayList<>(waitingForConfirmMap.values());
	}

	@Override
	public void set(K key, V value) {
		attrMap.putIfAbsent(key, value);
	}

	@Override
	public V get(K key) {
		return attrMap.get(key);
	}

	private int getId(MqttMessage msg) {
		Object vheader = msg.variableHeader();
		if (vheader instanceof MqttPublishVariableHeader)
			return ((MqttPublishVariableHeader) msg.variableHeader()).messageId();
		else
			return ((MqttMessageIdVariableHeader) msg.variableHeader()).messageId();
	}

}
